package com.xxx.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xxx.common.base.bo.ListResult;
import com.xxx.common.web.exception.BusinessException;
import com.xxx.user.dao.mapper.RoleMapper;
import com.xxx.user.dao.mapper.RoleMenuMapper;
import com.xxx.user.domain.entity.RoleDO;
import com.xxx.user.domain.entity.RoleMenuDO;
import com.xxx.user.domain.enums.UserErrorCode;
import com.xxx.user.dto.RoleCreateReqDTO;
import com.xxx.user.dto.RoleGetAllReqDTO;
import com.xxx.user.dto.RoleGetAllResDTO;
import com.xxx.user.dto.RoleUpdateReqDTO;
import com.xxx.user.service.MenuService;
import com.xxx.user.service.RoleService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;

@Slf4j
@Service
@AllArgsConstructor
public class RoleServiceImpl implements RoleService {

    private final RoleMapper roleMapper;
    private final RoleMenuMapper roleMenuMapper;
    private final MenuService menuService;


    @Override
    @Transactional
    public String create(RoleCreateReqDTO param) {
        //判断角色是否存在
        RoleDO roleDO = roleMapper.selectOne(new LambdaQueryWrapper<RoleDO>()
                .select(RoleDO::getId, RoleDO::getRoleName)
                .eq(RoleDO::getRoleKey, param.getRoleKey()), false);
        if (roleDO != null) {
            throw new BusinessException(UserErrorCode.SYSTEM_ERROR.getCode(), "角色已经存在！");
        }

        //插入新角色
        RoleDO insertRoleDO = new RoleDO();
        BeanUtil.copyProperties(param, insertRoleDO);
        roleMapper.insert(insertRoleDO);

        if (!CollectionUtils.isEmpty(param.getMenuList())) {
            //插入角色信息
            List<RoleMenuDO> roleMenuDOS = getRoleMenus(param.getMenuList(), insertRoleDO.getId());
            roleMenuMapper.batchInsert(roleMenuDOS);
            //更新缓存
            menuService.refreshMenuCache(param.getMenuList());
        }

        return "创建成功！";
    }

    @Override
    @Transactional
    public String update(RoleUpdateReqDTO param) {

        RoleDO roleDO = roleMapper.selectOne(new LambdaQueryWrapper<RoleDO>()
                .select(RoleDO::getId, RoleDO::getRoleName)
                .eq(RoleDO::getRoleKey, param.getRoleKey()), false);
        if (roleDO != null && !roleDO.getId().equals(param.getId())) {
            throw new BusinessException(UserErrorCode.SYSTEM_ERROR.getCode(), "角色已经存在！");
        }

        //更新角色信息
        RoleDO updateRoleDO = new RoleDO();
        BeanUtil.copyProperties(param, updateRoleDO);
        roleMapper.updateById(updateRoleDO);

        //更新菜单信息
        roleMenuMapper.delete(new LambdaQueryWrapper<RoleMenuDO>().eq(RoleMenuDO::getRoleId, param.getId()));
        if (!CollectionUtils.isEmpty(param.getMenuList())) {
            List<RoleMenuDO> roleMenuDOS = getRoleMenus(param.getMenuList(), param.getId());
            roleMenuMapper.batchInsert(roleMenuDOS);
            //更新缓存
            menuService.refreshMenuCache(param.getMenuList());
        }

        return "更新成功！";
    }


    @Override
    public String delete(List<Long> ids) {
        roleMapper.deleteBatchIds(ids);
        return "删除成功！";
    }

    @Override
    public ListResult<RoleGetAllResDTO> getAll(RoleGetAllReqDTO param) {

        IPage<RoleDO> page = new Page<>(param.getPageNum(), param.getPageSize(), param.getIsCount());
        IPage<RoleDO> selectPage = roleMapper.selectPage(page, new LambdaQueryWrapper<RoleDO>()
                .like(ObjectUtils.isNotEmpty(param.getRoleName()), RoleDO::getRoleName, param.getRoleName())
                .like(ObjectUtils.isNotEmpty(param.getRoleKey()), RoleDO::getRoleKey, param.getRoleKey())
                .eq(!ObjectUtils.isEmpty(param.getStatus()), RoleDO::getStatus, param.getStatus()));

        List<RoleGetAllResDTO> roleGetAllResDTOS = selectPage.getRecords().stream()
                .map(it -> {
                    RoleGetAllResDTO resDTO = new RoleGetAllResDTO();
                    BeanUtil.copyProperties(it, resDTO);
                    return resDTO;
                }).toList();

        ListResult<RoleGetAllResDTO> result = new ListResult<>();
        result.setList(roleGetAllResDTOS);
        result.setTotalNum((int) selectPage.getTotal());
        return result;
    }

    /*** 数据处理 */
    private List<RoleMenuDO> getRoleMenus(List<Long> menuList, Long id) {
        return menuList.stream().map(it -> {
            RoleMenuDO roleMenuDO = new RoleMenuDO();
            roleMenuDO.setRoleId(id);
            roleMenuDO.setMenuId(it);
            return roleMenuDO;
        }).toList();
    }
}
